//
// Created by hjie on 23-5-13.
//

#ifndef LOOP_EVENT_REDIS_MESSAGE_H
#define LOOP_EVENT_REDIS_MESSAGE_H
#include <vector>
#include <string>
#include <map>
#include <set>
// type : string / length string / array length string / number / error / internal command

enum RedisMessageType
{
    EmStringType       = 0,
    EmLengthStringType = 1,
    EmArrayStringType  = 2,
    EmNumberType       = 3,
    EmErrorType        = 4,
    EmInternalType     = 5
};

enum EmRedisParseStatus
{
    EmParseStatusNone     = 0x00,
    EmParseStatusFinish   = 0x01,
    EmParseStatusNeedData = 0x02,
    EmParseStatusError    = 0x03,
};

class RedisMessage
{
public:
    RedisMessage(RedisMessageType type);
    virtual ~RedisMessage() {}
    static RedisMessage * ParseRedisMessage(const uint8_t * data, int length, int & use_length, EmRedisParseStatus & status);
    static RedisMessage * ParseCommand(const std::string & command_line);
    virtual bool ParseMessage(const uint8_t * data, int length, int & use_length) = 0;
    virtual bool ComposeMessage(std::string & content) { return true; }

    RedisMessageType GetMessageType() { return m_type; }
private:
    RedisMessageType m_type;
};

class RedisMessageString : public RedisMessage
{
public:
    RedisMessageString();
    virtual ~RedisMessageString() = default;
    bool ParseMessage(const uint8_t *data, int length, int & use_length) override;
public:
    std::string Show() { return m_value;}
private:
    const char m_prefix{'+'};
    std::string m_value;
};

class RedisMessageLengthString : public RedisMessage
{
public:
    RedisMessageLengthString();
    virtual ~RedisMessageLengthString() = default;
    bool ParseMessage(const uint8_t *data, int length, int &use_length) override;
    bool ComposeMessage(std::string &content) override;
public:
    std::string Show() { return m_value; }
    int GetLength()    { return m_value.size(); }
    void Value(const std::string & value) { m_value = value; }
private:
    const char m_prefix{'$'};
    std::string m_value;
};

class RedisMessageArray : public RedisMessage
{
public:
    RedisMessageArray();
    virtual ~RedisMessageArray();
    bool ParseMessage(const uint8_t *data, int length, int &use_length) override;
    bool ComposeMessage(std::string &content) override;
public:
    std::vector<RedisMessage*> & GetMessageVector() { return m_value_vec; }
    void AddMessage(RedisMessage * message) { m_value_vec.push_back(message); }
private:
    const char m_prefix{'*'};
    std::vector<RedisMessage*> m_value_vec;
};

class RedisMessageNumber : public RedisMessage
{
public:
    RedisMessageNumber();
    virtual ~RedisMessageNumber() = default;
    bool ParseMessage(const uint8_t *data, int length, int &use_length) override;
    bool ComposeMessage(std::string &content) override;
public:
    int Number() { return m_number_value; }
    void Value(int number) { m_number_value = number; }
private:
    const char m_prefix{':'};
    // maybe change to double
    int m_number_value;
};

class RedisMessageError : public RedisMessage
{
public:
    RedisMessageError();
    virtual ~RedisMessageError() = default;
    bool ParseMessage(const uint8_t *data, int length, int &use_length) override;
public:
    std::string Error() { return m_value; }
private:
    const char m_prefix{'-'};
    std::string m_value;
};

class RedisInternalMessage : public RedisMessage
{
public:
    RedisInternalMessage();
    ~RedisInternalMessage() = default;
    bool ParseMessage(const uint8_t * data, int length, int & use_length) override;
    bool ComposeMessage(std::string & content) override;
public:
    std::string String();
private:
    static std::set<std::string> m_internal_command;
};

#endif //LOOP_EVENT_REDIS_MESSAGE_H
